import { Button, Card, Input, InputNumber, Select } from "antd";
import Table, { type ColumnsType } from "antd/es/table";
import { useContext, useMemo, useState } from "react";
import { toast } from "sonner";
import type { AutoCodePart } from "./entity";
import useDictionary from "@/hooks/system/useDictionary";
import { HolderOutlined } from "@ant-design/icons";

import type { DragEndEvent } from '@dnd-kit/core';
import { DndContext } from '@dnd-kit/core';
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import {
  arrayMove,
  SortableContext,
  useSortable,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import React from "react";

interface AutoCodePartProps {
  ruleId: React.Key;
	loading: boolean;
	partList: AutoCodePart[];
	setPartList: React.Dispatch<React.SetStateAction<AutoCodePart[]>>;
}

interface RowContextProps {
  setActivatorNodeRef?: (element: HTMLElement | null) => void;
  listeners?: SyntheticListenerMap;
}

interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
  'data-row-key': string;
}

const RowContext = React.createContext<RowContextProps>({});

const DragHandle: React.FC = () => {
  const { setActivatorNodeRef, listeners } = useContext(RowContext);
  return (
    <Button
      type="text"
      size="small"
      icon={<HolderOutlined />}
      style={{ cursor: 'move' }}
      ref={setActivatorNodeRef}
      {...listeners}
    />
  );
};

const Row: React.FC<RowProps> = (props) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    setActivatorNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: props['data-row-key'] });

  const style: React.CSSProperties = {
    ...props.style,
    transform: CSS.Translate.toString(transform),
    transition,
    ...(isDragging ? { position: 'relative', zIndex: 9999 } : {}),
  };

  const contextValue = useMemo<RowContextProps>(
    () => ({ setActivatorNodeRef, listeners }),
    [setActivatorNodeRef, listeners],
  );

  return (
    <RowContext.Provider value={contextValue}>
      <tr {...props} ref={setNodeRef} style={style} {...attributes} />
    </RowContext.Provider>
  );
};

const AutoCodePartPage: React.FC<AutoCodePartProps> = ({ ruleId, loading, partList, setPartList }) => {
	const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);

  const partTypeOptions = useDictionary("auto_code_part_type");
  const cycleMethodOptions = useDictionary("auto_code_part_cycle_type");
  const dateFormOptions = useDictionary("sys_date_format");

	const getFieldColumns = (
		handleFieldChange: (id: React.Key, field: string, value: any) => void,
	): ColumnsType<AutoCodePart> =>  {
    const isEditable = (record: AutoCodePart, type: 'FIXCHAR' | 'INPUTCHAR' | 'NOWDATE' | 'SERIALNO') =>
      record.partType === type;
    
    return [
    { key: 'sort', align: 'center', width: 80, render: () => <DragHandle /> },
		{
			title: "分段序号",
			width: 120,
			key: "partIndex",
			dataIndex: "partIndex",
		},
		{
			title: "分段名称",
			width: 120,
			key: "partName",
			dataIndex: "partName",
      render: (text, record) => (
				<Input 
          allowClear
          value={text} 
          onChange={(e) => {
            const newValue = e.target.value.trim(); // 去除首尾空格
            
            handleFieldChange(record.id, "partName", newValue);
          }}
          placeholder="请输入分段名称）"
        />
			),
		},
		{
			title: "分段类型",
			width: 120,
			key: "partType",
			dataIndex: "partType",
      render: (text, record) => (
				<Select
					value={text}
					allowClear
					dropdownStyle={{ minWidth: 200 }}
					style={{ width: "100%" }}
					onChange={(value) => handleFieldChange(record.id, "partType", value)}
					options={partTypeOptions}
				/>
			),
		},
    {
			title: "固定字符",
			width: 120,
			key: "fixCharacter",
			dataIndex: "fixCharacter",
      render: (text, record) => (
				<Input 
          allowClear
          disabled={!isEditable(record, "FIXCHAR")}
          value={text} 
          onChange={(e) => {
            const newValue = e.target.value.trim(); // 去除首尾空格
            
            handleFieldChange(record.id, "fixCharacter", newValue);
          }}
          placeholder="请输入固定字符"
        />
			),
		},
		{
			title: "分段长度",
			width: 120,
			key: "partLength",
			dataIndex: "partLength",
      render: (text, record) => (
				<InputNumber 
          value={text} 
          onChange={(e) => {
            handleFieldChange(record.id, "partLength", e);
          }}
          placeholder="分段长度"
        />
			),
		},
		{
			title: "日期格式",
			width: 120,
			key: "dateFormat",
			dataIndex: "dateFormat",
      render: (text, record) => (
				<Select
          disabled={!isEditable(record, "NOWDATE")}
					value={text}
					allowClear
					dropdownStyle={{ minWidth: 200 }}
					style={{ width: "100%" }}
					onChange={(value) => handleFieldChange(record.id, "dateFormat", value)}
					options={dateFormOptions}
				/>
			),
		},
		{
			title: "输入字符",
			width: 120,
			key: "inputCharacter",
			dataIndex: "inputCharacter",
      render: (text, record) => (
				<Input 
          allowClear
          disabled={!isEditable(record, "INPUTCHAR")}
          value={text} 
          onChange={(e) => {
            const newValue = e.target.value.trim(); // 去除首尾空格
            
            handleFieldChange(record.id, "inputCharacter", newValue);
          }}
          placeholder="请输入输入字符"
        />
			),
		},
		{
			title: "流水号起始值",
			width: 120,
			key: "serialStartNo",
			dataIndex: "serialStartNo",
      render: (text, record) => (
				<InputNumber 
          disabled={!isEditable(record, "SERIALNO")}
          value={text}
          onChange={(e) => {
            handleFieldChange(record.id, "serialStartNo", e);
          }}
          placeholder="请输入流水号起始值"
        />
			),
		},
		{
			title: "流水号步长",
			width: 120,
			key: "serialStep",
			dataIndex: "serialStep",
      render: (text, record) => (
				<InputNumber 
          disabled={!isEditable(record, "SERIALNO")}
          value={text} 
          onChange={(e) => {
            handleFieldChange(record.id, "serialStep", e);
          }}
          placeholder="请输入流水号步长"
        />
			),
		},
		{
			title: "循环方式",
			width: 120,
			key: "cycleMethod",
			dataIndex: "cycleMethod",
      render: (text, record) => (
				<Select
          disabled={!isEditable(record, "SERIALNO")}
					value={text}
					allowClear
					dropdownStyle={{ minWidth: 200 }}
					style={{ width: "100%" }}
					onChange={(value) => handleFieldChange(record.id, "cycleMethod", value)}
					options={cycleMethodOptions}
				/>
			),
		},
		{
			title: "备注",
			width: 120,
			key: "remark",
			dataIndex: "remark",
      render: (text, record) => (
				<Input 
          allowClear
          value={text} 
          onChange={(e) => {
            const newValue = e.target.value.trim();
            
            handleFieldChange(record.id, "remark", newValue);
          }}
          placeholder="请输入备注"
        />
			),
		},
	]};

  const onDragEnd = ({ active, over }: DragEndEvent) => {
    if (active.id !== over?.id) {
      setPartList((prevState) => {
        const activeIndex = prevState.findIndex((record) => record.id === active?.id);
        const overIndex = prevState.findIndex((record) => record.id === over?.id);
        // 排序后的新数组
        const newList = arrayMove(prevState, activeIndex, overIndex);

        // 重新设置 partIndex
        return newList.map((item, index) => ({
          ...item,
          partIndex: index + 1, // 从 1 开始编号
        }));
      });
    }
  };

	// 处理字段变更
	const handleFieldChange = (id: React.Key, field: string, value: any) => {
		if (field === "partType" && !value.trim()) {
			toast.error("分段类型不能为空");
			return;
		}
		setPartList((prevData) => prevData.map((item) => (item.id === id ? { ...item, [field]: value } : item)));
	};

  //检验是否输入值
  const validatePartsBeforeAdd = (): boolean => {
    for (const part of partList) {
      if (!part.partName) {
        toast.error(`（序号 ${part.partIndex}）分段名称不能为空`);
        return false;
      }
      const { partType } = part;
      switch (partType) {
        case 'FIXCHAR':
          if (!part.fixCharacter) {
            toast.error(`（序号 ${part.partIndex}）固定字符不能为空`);
            return false;
          }
          break;
        case 'INPUTCHAR':
          if (!part.inputCharacter) {
            toast.error(`（序号 ${part.partIndex}）输入字符不能为空`);
            return false;
          }
          break;
        case 'NOWDATE':
          if (!part.dateFormat) {
            toast.error(`（序号 ${part.partIndex}）日期格式不能为空`);
            return false;
          }
          break;
        case 'SERIALNO':
          if (
            part.serialStartNo === undefined ||
            part.serialStep === undefined ||
            !part.cycleMethod
          ) {
            toast.error(`（序号 ${part.partIndex}）流水号相关字段不能为空`);
            return false;
          }
          break;
        default:
          toast.error(`（序号 ${part.partIndex}）分段类型未选择`);
          return false;
      }
    }
    return true;
  };  

	const handleAdd = () => {
    if (!validatePartsBeforeAdd()) {
      return; // 校验未通过，不执行新增
    }

		const newPart: AutoCodePart = {
			id: Date.now().toString(), // 临时唯一 ID
      ruleId: ruleId,
			partIndex: partList.length + 1,
      partType: undefined, 
		};

		setPartList((prevParts) => [...prevParts, newPart]);
	};

	const handleDelete = async () => {
		if (selectedRowKeys.length === 0) {
			toast.warning("请至少选择一行数据");
			return;
		}
		setPartList((prevList) => prevList.filter((item) => !selectedRowKeys.includes(item.id)));
		setSelectedRowKeys([]);
		toast.success("删除成功");
	};

  	// 获取字段列配置
	const columns = getFieldColumns(handleFieldChange);

	return (
		<>
			<Card>
				<div className="flex justify-between mb-4">
					<div className="flex gap-2">
						<Button type="primary" onClick={handleAdd}>
							新增
						</Button>
						<Button danger disabled={selectedRowKeys.length === 0} onClick={handleDelete}>
							删除
						</Button>
					</div>
				</div>
        <DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
          <SortableContext items={partList.map((i) => i.id)} strategy={verticalListSortingStrategy}>
            <Table
              rowKey="id"
              size="small"
              scroll={{ y: "calc(100vh - 200px)" }}
              components={{ body: { row: Row } }}
              loading={loading}
              pagination={false}
              columns={columns}
              dataSource={partList}
              rowSelection={{
                type: "checkbox",
                selectedRowKeys: selectedRowKeys,
                onChange: (selectedKeys) => {
                  setSelectedRowKeys(selectedKeys as string[]);
                },
              }}
            />
          </SortableContext>
        </DndContext>
			</Card>
		</>
	);
};

export default AutoCodePartPage;
